/** * Copyright (c) 2012 Edgar Espina * * This file is part of Handlebars.java. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package mustache.specs; import static org.junit.Assert.assertEquals; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.commons.io.FileUtils; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ComparisonFailure; import org.junit.Test; import org.junit.runner.RunWith; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.HandlebarsException; import com.github.jknack.handlebars.HelperRegistry; import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.custom.Blog; import com.github.jknack.handlebars.custom.Comment; @RunWith(SpecRunner.class) public abstract class SpecTest { private static class Report { public void header(final int size) { StringBuilder buffer = new StringBuilder(); for (int i = 0; i < size; i++) { buffer.append("*"); } Handlebars.log(buffer.toString()); } public void append(final Object message) { Handlebars.log(message == null ? "" : message.toString()); } public void append(final Object message, final Object... arguments) { Handlebars.log(message == null ? "" : message.toString(), arguments); } } private static long start; private static long count; private Spec spec; public SpecTest(final Spec spec) { this.spec = spec; } @BeforeClass public static void onStart() { start = System.currentTimeMillis(); } @AfterClass public static void onFinish() { long end = System.currentTimeMillis(); System.out.printf("Number of executions: %s\n", count); System.out.printf("Total Time: %sms\n", end - start); } @Test public void run() throws HandlebarsException, IOException { if (!skip(spec)) { run(alter(spec)); } else { Report report = new Report(); report.header(80); report.append("Skipping Test: %s", spec.id()); report.header(80); throw new SkipTestException(spec.name()); } } public static Collection<Object[]> data(final String filename) throws IOException { return data(SpecTest.class, filename); } public static String path(final Class<?> loader) { return "/" + loader.getPackage().getName().replace(".", "/") + "/"; } @SuppressWarnings("unchecked") public static Collection<Object[]> data(final Class<?> loader, final String filename) throws IOException { Constructor constructor = new Constructor(); constructor.addTypeDescription(new TypeDescription(Blog.class, "!blog")); constructor.addTypeDescription(new TypeDescription(Comment.class, "!comment")); constructor.addTypeDescription(new TypeDescription(Map.class, "!code")); Yaml yaml = new Yaml(constructor); String location = path(loader) + filename; String input = FileUtils.readFileToString(new File("src/test/resources", location)); Map<String, Object> data = (Map<String, Object>) yaml.load(input); List<Map<String, Object>> tests = (List<Map<String, Object>>) data.get("tests"); int number = 0; Collection<Object[]> dataset = new ArrayList<Object[]>(); for (Map<String, Object> test : tests) { test.put("number", number++); dataset.add(new Object[]{new Spec(test) }); } return dataset; } protected boolean skip(final Spec spec) { return false; } protected Spec alter(final Spec spec) { return spec; } private void run(final Spec spec) throws IOException { count++; Report report = new Report(); report.header(80); report.append("* %s", spec.description()); final String input = spec.template(); final String expected = spec.expected(); Object data = spec.data(); report.append("DATA:"); report.append(data.toString()); report.append("PARTIALS:"); report.append(spec.partials()); report.append("INPUT:"); report.append(input); report.append("EXPECTED:"); report.append(expected); long startCompile = System.currentTimeMillis(); Handlebars handlebars = new Handlebars(new SpecResourceLocator(spec)); handlebars.setPrettyPrint(true); configure(handlebars); Template template = handlebars.compile("template"); long endCompile = System.currentTimeMillis(); long startMerge = System.currentTimeMillis(); CharSequence output = template.apply(data); long endMerge = System.currentTimeMillis(); long total = endMerge - startCompile; long compile = endCompile - startCompile; long merge = endMerge - startMerge; try { assertEquals(expected, output); report.append("OUTPUT:"); report.append(output); } catch (HandlebarsException ex) { Handlebars.error(ex.getMessage()); } catch (ComparisonFailure ex) { report.append("FOUND:"); report.append(ex.getActual()); throw ex; } finally { report.append("TOTAL : %sms", total); if (total > 0) { report.append(" (%s%%)compile: %sms", compile * 100 / total, compile); report.append(" (%s%%)merge : %sms", merge * 100 / total, merge); } report.header(80); } } protected HelperRegistry configure(final Handlebars handlebars) { return handlebars; } @Before public void initJUnit() throws IOException { // Init junit classloader. This reduce the time reported during execution. new Handlebars(); } }